package com.xxx.springboot.pojo;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 自定义线程池
 */
public class MyThreadPool {

	static final Logger LOGGER = LoggerFactory.getLogger(MyThreadPool.class);
	
	// 默认线程池线程数（CPU核心数*2）
	private static final int DEFAULT_CORE_SIZE = Runtime.getRuntime().availableProcessors() * 2;
	
	// 线程池名称
	private static final String THREAD_POOL_NAME = "MyThreadPool-%d";
	
	// 创建线程工厂
	private static final ThreadFactory FACTORY = new BasicThreadFactory.Builder()
														.namingPattern(THREAD_POOL_NAME)
											            .daemon(true)
											            .build();
	
	// 线程默认存活时长
    private static final long DEFAULT_KEEP_ALIVE = 60L;
    
    // 存放任务的阻塞队列的默认大小
    private static final int DEFAULT_SIZE = 500;
    
    // 存放任务的阻塞队列
    private static BlockingQueue<Runnable> executeQueue = new ArrayBlockingQueue<>(DEFAULT_SIZE);

    // 线程池
    private static ExecutorService executor;

    // 系统启动时初始化线程池
    static {
    	try {
    		LOGGER.info("init executor......");
    		executor = new ThreadPoolExecutor(
	    				DEFAULT_CORE_SIZE,
	    				DEFAULT_CORE_SIZE+2,
	    				DEFAULT_KEEP_ALIVE,
	    				TimeUnit.SECONDS,
	    				executeQueue,
	    				FACTORY
    				);
    		
    		// 给线程池添加一个关闭钩子
    		LOGGER.info("add a shutdown hook ......");
    		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    			
				@Override
				public void run() {
					LOGGER.info("MyThreadPool shutting down.");
                    executor.shutdown();
					
                    try {
                    	// 等待1秒超市后，立即停止线程池
                    	if(!executor.awaitTermination(1, TimeUnit.SECONDS)) {
                    		LOGGER.error("MyThreadPool shutdown immediately due to wait timeout.");
                            executor.shutdownNow();
                    	}
                    } catch (Exception e) {
                    	LOGGER.error("MyThreadPool shutdown interrupted.");
                        executor.shutdownNow();
                    }
                    LOGGER.info("MyThreadPool shutdown complete.");
				}
    		}));
    		
    	} catch (Exception e) {
    		LOGGER.error("MyThreadPool init error.", e);
            throw new ExceptionInInitializerError(e);
    	}
    }
    
    // 防止被实例化
    private MyThreadPool() {
    }
    
    /**
     * 执行任务（不需要任务执行结果）
     */
    public static boolean execute(Runnable task) {
    	try {
            executor.execute(task);
        } catch (RejectedExecutionException e) {
            LOGGER.error("Task executing was rejected.", e);
            return false;
        }
        return true;    	
    }
    
    /**
     * 提交任务（需要等待返回结果）
     */
    public static <T> Future<T> submit(Callable<T> task){
    	try {
    		return executor.submit(task);
        } catch (RejectedExecutionException e) {
        	LOGGER.error("Task executing was rejected.", e);
            throw new UnsupportedOperationException("Unable to submit the task, rejected.", e);
        }
    }
    
    /**
     * main
     * @param args
     */
    public static void main(String[] args) {
    	for(int i=1; i<100; i++) {
    		executor.execute(new Runnable() {
    			@Override
    			public void run() {
    				System.out.println("main run----"+System.currentTimeMillis());
    			}
    		});
    	}
	}
}
